package common

import (
	"bytes"
	"errors"
	"fmt"
	"gitee.com/kinwyb/appTools/log"
	"gitee.com/kinwyb/conv"
	emailpkg "github.com/jordan-wright/email"
	"net/smtp"
	"strings"
)

type Email interface {
	// SetUserName 设置发件人名称
	SetUserName(name string)
	// Send 发邮件
	Send(to, cc []string, subject, body string, attach ...EmailAttach) error
}

// 邮件服务配置
type emailCfg struct {
	User     string
	UserName string
	Password string
	Host     string
	Port     int
}

// 配置是否有效
func (e emailCfg) complate() bool {
	return e.User != "" && e.Password != "" && e.Host != ""
}

// SetUserName 设置发件人名称
func (e *emailCfg) SetUserName(name string) {
	e.UserName = name
}

// NewEmail 设置邮件用户
func NewEmail(user string, password string, serverHost string) Email {
	var e emailCfg
	if user != "" {
		e.User = user
	}
	if password != "" {
		e.Password = password
	}
	if serverHost != "" {
		serverHosts := strings.Split(serverHost, ":")
		if len(serverHosts) < 2 {
			serverHosts = append(serverHosts, "25")
		}
		if serverHosts[0] != "" {
			e.Host = serverHosts[0]
		}
		e.Port = conv.ToIntDefault(serverHosts[1], 25)
	}
	return &e
}

// EmailAttach 邮件附件
type EmailAttach struct {
	data     []byte
	fileName string
}

// NewEmailAttach 初始化附件信息
func NewEmailAttach(data []byte, fileName string) EmailAttach {
	return EmailAttach{
		data:     data,
		fileName: fileName,
	}
}

func (a EmailAttach) toEmailAttach(es *emailpkg.Email) {
	if len(a.data) < 1 || es == nil {
		return
	}
	if a.fileName == "" {
		a.fileName = "undefine"
	}
	_, _ = es.Attach(bytes.NewReader(a.data), a.fileName, "")
}

// Send 发送邮件
func (e emailCfg) Send(to, cc []string, subject, body string, attach ...EmailAttach) error {
	if len(to) < 1 || to[0] == "" {
		return errors.New("收件人不能为空")
	} else if !e.complate() {
		return errors.New("email配置空")
	}
	es := emailpkg.NewEmail()
	if e.UserName != "" {
		es.From = e.UserName + "<" + e.User + ">"
	} else {
		es.From = e.User
	}
	es.To = to
	es.Cc = cc
	es.Subject = subject
	es.HTML = []byte(body + "<br /><br />")
	if len(attach) > 0 {
		for _, v := range attach {
			v.toEmailAttach(es)
		}
	}
	err := es.Send(fmt.Sprintf("%s:%d", e.Host, e.Port),
		smtp.PlainAuth("", e.User, e.Password, e.Host))
	if err != nil {
		log.AppTool.WithError(err).Error("邮件发送失败")
		return errors.New("邮件发送失败")
	}
	return nil
}
